import { Request, Response, NextFunction } from 'express';
import { prisma } from '../../config/database';
import { logger } from '../../utils/logger';
import { BaseController } from '../../utils/autoBind';
import { ResponseUtils } from '../../utils/responseUtils';
import { BUSINESS_ERROR_CODES, VALIDATION_ERROR_CODES } from '../../utils/errorCodes';
import * as ExcelJS from 'exceljs';

export class LogController extends BaseController {
  // 获取操作日志列表
  async getOperationLogs(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { page = 1, limit = 20, search = '', userId, action, startDate, endDate } = req.query;
      const pageNum = parseInt(page as string);
      const limitNum = parseInt(limit as string);
      const skip = (pageNum - 1) * limitNum;

      // 构建查询条件
      const where: any = {};

      if (search) {
        where.OR = [
          { action: { contains: search as string } },
          { details: { contains: search as string } },
          { ipAddress: { contains: search as string } }
        ];
      }

      if (userId) {
        where.userId = parseInt(userId as string);
      }

      if (action) {
        where.action = action;
      }

      if (startDate || endDate) {
        where.createdAt = {};
        if (startDate) {
          where.createdAt.gte = new Date(startDate as string);
        }
        if (endDate) {
          where.createdAt.lte = new Date(endDate as string);
        }
      }

      // 查询操作日志列表
      const [logs, total] = await Promise.all([
        prisma.operationLog.findMany({
          where,
          select: {
            id: true,
            action: true,
            details: true,
            ipAddress: true,
            userAgent: true,
            createdAt: true,
            user: {
              select: {
                id: true,
                username: true,
                realName: true
              }
            }
          },
          skip,
          take: limitNum,
          orderBy: { createdAt: 'desc' }
        }),
        prisma.operationLog.count({ where })
      ]);

      ResponseUtils.paginated(res, logs, total, pageNum, limitNum);
    } catch (error) {
      next(error);
    }
  }

  // 获取操作日志详情
  async getOperationLogById(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;
      const logId = parseInt(id);

      if (isNaN(logId)) {
        ResponseUtils.sendError(res, VALIDATION_ERROR_CODES.FIELD_TYPE_ERROR, '无效的日志ID');
        return;
      }

      const log = await prisma.operationLog.findUnique({
        where: { id: logId },
        select: {
          id: true,
          action: true,
          details: true,
          ipAddress: true,
          userAgent: true,
          createdAt: true,
          user: {
            select: {
              id: true,
              username: true,
              realName: true,
              email: true
            }
          }
        }
      });

      if (!log) {
        ResponseUtils.sendError(res, BUSINESS_ERROR_CODES.LOG_NOT_FOUND, '日志不存在');
        return;
      }

      ResponseUtils.success(res, log);
    } catch (error) {
      next(error);
    }
  }

  // 清空操作日志
  async clearOperationLogs(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { beforeDate } = req.body;

      const where: any = {};
      if (beforeDate) {
        where.createdAt = {
          lt: new Date(beforeDate)
        };
      }

      const result = await prisma.operationLog.deleteMany({ where });

      logger.info(`清空操作日志: 删除了 ${result.count} 条记录`);
      ResponseUtils.success(res, { deletedCount: result.count });
    } catch (error) {
      next(error);
    }
  }

  // 获取日志统计信息
  async getLogStats(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { startDate, endDate } = req.query;

      // 构建日期范围条件
      const dateFilter: any = {};
      if (startDate || endDate) {
        dateFilter.createdAt = {};
        if (startDate) {
          dateFilter.createdAt.gte = new Date(startDate as string);
        }
        if (endDate) {
          dateFilter.createdAt.lte = new Date(endDate as string);
        }
      }

      // 获取各种统计信息
      const [
        totalLogs,
        todayLogs,
        userStats,
        actionStats,
        resourceStats,
        hourlyStats,
        dailyStats
      ] = await Promise.all([
        // 总日志数
        prisma.operationLog.count({ where: dateFilter }),

        // 今日日志数
        prisma.operationLog.count({
          where: {
            ...dateFilter,
            createdAt: {
              gte: new Date(new Date().setHours(0, 0, 0, 0))
            }
          }
        }),

        // 用户操作统计
        prisma.operationLog.groupBy({
          by: ['userId'],
          where: dateFilter,
          _count: { id: true },
          orderBy: { _count: { id: 'desc' } },
          take: 10
        }),

        // 操作类型统计
        prisma.operationLog.groupBy({
          by: ['action'],
          where: dateFilter,
          _count: { id: true },
          orderBy: { _count: { id: 'desc' } },
          take: 10
        }),

        // 资源类型统计
        prisma.operationLog.groupBy({
          by: ['resource'],
          where: dateFilter,
          _count: { id: true },
          orderBy: { _count: { id: 'desc' } },
          take: 10
        }),

        // 小时统计
        prisma.operationLog.groupBy({
          by: ['createdAt'],
          where: dateFilter,
          _count: { id: true }
        }),

        // 每日统计
        prisma.operationLog.groupBy({
          by: ['createdAt'],
          where: dateFilter,
          _count: { id: true }
        })
      ]);

      // 处理小时统计
      const hourlyData = hourlyStats.reduce((acc: any, stat: any) => {
        const hour = new Date(stat.createdAt).getHours();
        acc[hour] = (acc[hour] || 0) + stat._count.id;
        return acc;
      }, {});

      // 处理每日统计
      const dailyData = dailyStats.reduce((acc: any, stat: any) => {
        const date = new Date(stat.createdAt).toISOString().split('T')[0];
        acc[date] = (acc[date] || 0) + stat._count.id;
        return acc;
      }, {});

      // 获取用户信息
      const userIds = userStats.map(stat => stat.userId).filter((id): id is number => id !== null);
      const users = await prisma.user.findMany({
        where: { id: { in: userIds } },
        select: { id: true, username: true, realName: true }
      });

      const userStatsWithInfo = userStats.map(stat => {
        const user = users.find(u => u.id === stat.userId);
        return {
          userId: stat.userId,
          username: user?.username || '未知用户',
          realName: user?.realName || '',
          count: stat._count.id
        };
      });

      ResponseUtils.success(res, {
        totalLogs,
        todayLogs,
        userStats: userStatsWithInfo,
        actionStats: actionStats.map(stat => ({
          action: stat.action,
          count: stat._count.id
        })),
        resourceStats: resourceStats.map(stat => ({
          resource: stat.resource,
          count: stat._count.id
        })),
        hourlyStats: hourlyData,
        dailyStats: dailyData
      });
    } catch (error) {
      next(error);
    }
  }

  // 获取日志分析报告
  async getLogAnalytics(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { startDate, endDate } = req.query;

      // 构建日期范围条件
      const dateFilter: any = {};
      if (startDate || endDate) {
        dateFilter.createdAt = {};
        if (startDate) {
          dateFilter.createdAt.gte = new Date(startDate as string);
        }
        if (endDate) {
          dateFilter.createdAt.lte = new Date(endDate as string);
        }
      }

      // 获取分析数据
      const [
        totalLogs,
        uniqueUsers,
        uniqueActions,
        uniqueResources,
        errorLogs,
        successLogs,
        topUsers,
        topActions,
        topResources,
        recentActivity
      ] = await Promise.all([
        // 总日志数
        prisma.operationLog.count({ where: dateFilter }),

        // 唯一用户数
        prisma.operationLog.groupBy({
          by: ['userId'],
          where: { ...dateFilter, userId: { not: null } },
          _count: { id: true }
        }),

        // 唯一操作类型数
        prisma.operationLog.groupBy({
          by: ['action'],
          where: dateFilter,
          _count: { id: true }
        }),

        // 唯一资源类型数
        prisma.operationLog.groupBy({
          by: ['resource'],
          where: dateFilter,
          _count: { id: true }
        }),

        // 错误日志数
        prisma.operationLog.count({
          where: {
            ...dateFilter,
            action: { contains: '错误' }
          }
        }),

        // 成功操作数
        prisma.operationLog.count({
          where: {
            ...dateFilter,
            action: { not: { contains: '错误' } }
          }
        }),

        // 最活跃用户
        prisma.operationLog.groupBy({
          by: ['userId'],
          where: { ...dateFilter, userId: { not: null } },
          _count: { id: true },
          orderBy: { _count: { id: 'desc' } },
          take: 5
        }),

        // 最常用操作
        prisma.operationLog.groupBy({
          by: ['action'],
          where: dateFilter,
          _count: { id: true },
          orderBy: { _count: { id: 'desc' } },
          take: 5
        }),

        // 最常用资源
        prisma.operationLog.groupBy({
          by: ['resource'],
          where: dateFilter,
          _count: { id: true },
          orderBy: { _count: { id: 'desc' } },
          take: 5
        }),

        // 最近活动
        prisma.operationLog.findMany({
          where: dateFilter,
          select: {
            id: true,
            action: true,
            resource: true,
            createdAt: true,
            user: {
              select: {
                id: true,
                username: true,
                realName: true
              }
            }
          },
          orderBy: { createdAt: 'desc' },
          take: 10
        })
      ]);

      // 获取用户信息
      const userIds = topUsers.map(stat => stat.userId).filter((id): id is number => id !== null);
      const users = await prisma.user.findMany({
        where: { id: { in: userIds } },
        select: { id: true, username: true, realName: true }
      });

      const topUsersWithInfo = topUsers.map(stat => {
        const user = users.find(u => u.id === stat.userId);
        return {
          userId: stat.userId,
          username: user?.username || '未知用户',
          realName: user?.realName || '',
          count: stat._count.id
        };
      });

      ResponseUtils.success(res, {
        summary: {
          totalLogs,
          uniqueUsers: uniqueUsers.length,
          uniqueActions: uniqueActions.length,
          uniqueResources: uniqueResources.length,
          errorLogs,
          successLogs,
          successRate: totalLogs > 0 ? ((totalLogs - errorLogs) / totalLogs * 100).toFixed(2) : '0'
        },
        topUsers: topUsersWithInfo,
        topActions: topActions.map(stat => ({
          action: stat.action,
          count: stat._count.id
        })),
        topResources: topResources.map(stat => ({
          resource: stat.resource,
          count: stat._count.id
        })),
        recentActivity
      });
    } catch (error) {
      next(error);
    }
  }

  // 导出操作日志
  async exportOperationLogs(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const {
        format = 'json',
        startDate,
        endDate,
        userId,
        action,
        resource,
        search
      } = req.query;

      // 构建查询条件
      const where: any = {};

      // 时间范围过滤
      if (startDate || endDate) {
        where.createdAt = {};
        if (startDate) {
          where.createdAt.gte = new Date(startDate as string);
        }
        if (endDate) {
          where.createdAt.lte = new Date(endDate as string);
        }
      }

      // 用户过滤
      if (userId) {
        where.userId = parseInt(userId as string);
      }

      // 操作类型过滤
      if (action) {
        where.action = action;
      }

      // 资源类型过滤
      if (resource) {
        where.resource = resource;
      }

      // 搜索过滤
      if (search) {
        where.OR = [
          { details: { contains: search as string } },
          { ipAddress: { contains: search as string } },
          { userAgent: { contains: search as string } },
          { user: { username: { contains: search as string } } },
          { user: { realName: { contains: search as string } } }
        ];
      }

      const logs = await prisma.operationLog.findMany({
        where,
        select: {
          id: true,
          action: true,
          resource: true,
          resourceId: true,
          details: true,
          ipAddress: true,
          userAgent: true,
          createdAt: true,
          user: {
            select: {
              id: true,
              username: true,
              realName: true,
              email: true
            }
          }
        },
        orderBy: { createdAt: 'desc' }
      });

      // 格式化数据
      const formattedLogs = logs.map(log => ({
        id: log.id,
        action: log.action, // 保持原始操作类型，不转换为中文
        resource: log.resource || '-',
        resourceId: log.resourceId || '-',
        details: this.formatDetails(log.details),
        ipAddress: log.ipAddress || '-',
        userAgent: log.userAgent || '-',
        username: log.user?.username || '-',
        realName: log.user?.realName || '-',
        email: log.user?.email || '-',
        createdAt: log.createdAt.toISOString().replace('T', ' ').substring(0, 19)
      }));

      if (format === 'excel') {
        await this.generateExcelExport(res, formattedLogs);
      } else if (format === 'csv') {
        this.generateCsvExport(res, formattedLogs);
      } else {
        // 默认JSON格式
        ResponseUtils.success(res, formattedLogs);
      }
    } catch (error) {
      next(error);
    }
  }
  private async generateExcelExport(res: Response, logs: any[]): Promise<void> {
    const workbook = new ExcelJS.Workbook();
    const worksheet = workbook.addWorksheet('操作日志');
  
    // 设置列标题
    worksheet.columns = [
      { header: 'ID', key: 'id', width: 10 },
      { header: '用户ID', key: 'userId', width: 10 },
      { header: '操作类型', key: 'action', width: 15 },
      { header: '资源类型', key: 'resource', width: 15 },
      { header: '资源ID', key: 'resourceId', width: 15 },
      { header: '操作详情', key: 'details', width: 40, style: { alignment: { wrapText: true } } },
      { header: 'IP地址', key: 'ipAddress', width: 15 },
      { header: '用户代理', key: 'userAgent', width: 30 },
      { header: '创建时间', key: 'createdAt', width: 20 }
    ];
  
    // 添加数据
    logs.forEach(log => {
      log.details = "";//this.formatDetailsForExport(log.details);
      worksheet.addRow(log);
    });
  
    // 设置表头样式
    const headerRow = worksheet.getRow(1);
    headerRow.font = { bold: true, color: { argb: 'FFFFFF' } };
    headerRow.fill = {
      type: 'pattern',
      pattern: 'solid',
      fgColor: { argb: '4472C4' }
    };
  
    // 设置边框
    worksheet.eachRow((row) => {
      row.eachCell((cell) => {
        cell.border = {
          top: { style: 'thin' },
          left: { style: 'thin' },
          bottom: { style: 'thin' },
          right: { style: 'thin' }
        };
      });
    });
  
    // 设置响应头
    res.setHeader('Content-Type', 'application/vnd.ms-excel');
    res.setHeader('Content-Disposition', `attachment; filename="operation_logs_${new Date().toISOString().split('T')[0]}.xlsx"`);
  
    // 写入响应
    await workbook.xlsx.write(res);
  }
  
  private generateCsvExport(res: Response, logs: any[]): void {
    const headers = [
      'ID', '用户ID', '操作类型', '资源类型', '资源ID', '操作详情', 'IP地址',
      '用户代理', '创建时间'
    ];
  
    const csvRows = logs.map(log => [
      log.id,
      log.userId,
      log.action,
      log.resource,
      log.resourceId,
      this.formatDetailsForExport(log.details),  // 替换换行以避免CSV行中断
      log.ipAddress,
      log.userAgent,
      log.createdAt
    ]);
  
    const csvContent = [headers, ...csvRows]
      .map(row => row.map(field => `"${field}"`).join(','))
      .join('\n');
  
    res.setHeader('Content-Type', 'text/csv; charset=utf-8');
    res.setHeader('Content-Disposition', `attachment; filename="operation_logs_${new Date().toISOString().split('T')[0]}.csv"`);
    res.send(csvContent);
  }
  
  private formatDetails(details: any): string {
    if (!details) return '-';
  
    if (typeof details === 'string') {
      return details;
    }
  
    if (typeof details === 'object') {
      try {
        return JSON.stringify(details);
      } catch {
        return String(details);
      }
    }
  
    return String(details);
  }
  
  private formatDetailsForExport(details: any): string {
    details = JSON.parse(details);
    return this.formatDetails(details).replace(/[\,]/g, '，');  // 将换行替换为管道符，便于单行显示
  }
} 